#include <png.h>
#include <graphics/PNGImageReader.h>
#include <graphics/ImageManager.h>

namespace ne
{
    ImagePtr PNGImageReader::loadImage(const std::string &fileName) const
    {
        FILE *file = fopen(fileName.c_str(), "rb");
        if (file == 0)
        {
            return ImagePtr();
        }

        png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
        if (png_ptr == 0)
        {
            return ImagePtr();
        }
        png_infop info_ptr = png_create_info_struct(png_ptr);
        if (info_ptr == 0)
        {
            return ImagePtr();
        }
        setjmp(png_jmpbuf(png_ptr));
        png_init_io(png_ptr, file);
        png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0);

        uint32_t width = png_get_image_width(png_ptr, info_ptr);
        uint32_t height = png_get_image_height(png_ptr, info_ptr);
        uint32_t colorType = png_get_color_type(png_ptr, info_ptr);
        uint32_t pixelSize = 0;
        PixelFormat format = PF_UNKNOWN;
        if (colorType == PNG_COLOR_TYPE_GRAY)
        {
            format = PF_ALPHA;
            pixelSize = 1;
        }
        else if (colorType == PNG_COLOR_TYPE_RGB)
        {
            format = PF_RGB;
            pixelSize = 3;
        }
        else if (colorType == PNG_COLOR_TYPE_RGBA)
        {
            format = PF_RGBA;
            pixelSize = 4;
        }

        ImagePtr pImage(ImageManager::GetSingleton().createImage(fileName, "ImageFiles", width, height, 1, format));

        png_bytep *rows;
        rows = png_get_rows(png_ptr, info_ptr);
        byte *data = pImage->getData();
        for (uint32_t i=0; i<height; ++i)
        {
            memcpy(&data[pixelSize * width * i], rows[height - i - 1], pixelSize * width);
        }
        png_destroy_read_struct(&png_ptr, &info_ptr, 0);
        fclose(file);

        return pImage;
    }
}

